package com.panfeng.xcloud.boss.provider.member.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.panfeng.xcloud.boss.provider.member.cache.CacheContext;
import com.panfeng.xcloud.boss.provider.member.dto.request.*;
import com.panfeng.xcloud.boss.provider.member.dto.response.CheckUserAccountRespDTO;
import com.panfeng.xcloud.boss.provider.member.dto.response.LoginRespDTO;
import com.panfeng.xcloud.boss.provider.member.dto.response.RefreshTokenRespDTO;
import com.panfeng.xcloud.boss.provider.member.dto.response.VerifiyCodeRespDTO;
import com.panfeng.xcloud.boss.provider.member.enums.LoginAccountTypeEnum;
import com.panfeng.xcloud.boss.provider.member.service.IUserBasicService;
import com.panfeng.xcloud.boss.provider.member.service.IUserSMSService;
import com.panfeng.xcloud.boss.provider.member.service.IUserTokenService;
import com.panfeng.xcloud.boss.provider.member.web.vo.request.*;
import com.panfeng.xcloud.boss.provider.member.web.vo.response.CheckUserAccountRespVO;
import com.panfeng.xcloud.boss.provider.member.web.vo.response.LoginRespVO;
import com.panfeng.xcloud.boss.provider.member.web.vo.response.RefreshTokenRespVO;
import com.panfeng.xcloud.common.core.enums.ResponseStatusEnum;
import com.panfeng.xcloud.common.core.enums.VerifiyCodeTypeEnum;
import com.panfeng.xcloud.common.core.exceptions.BaseBizException;
import com.panfeng.xcloud.common.core.utils.ConvertUtils;
import com.panfeng.xcloud.common.core.web.vo.EmptyResponseVO;
import com.panfeng.xcloud.common.core.web.vo.ResponseVO;
import com.panfeng.xcloud.common.security.annotation.MethodValidate;
import com.panfeng.xcloud.common.security.annotation.NotNeedAccess;
import com.panfeng.xcloud.common.security.web.support.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.regex.Pattern;

/**
 *
 * 用户认证登录模块
 *
 * @author xiaobo
 * @version 1.0
 * @since 2019-08-08
 */
//@ApiIgnore
@RestController
@RequestMapping("user/login")
@Api(tags = {"用户登录模块"})
@Slf4j
public class UserLoginController extends BaseController {

	@Autowired
	private CacheContext cacheContext;

	@Autowired
	private IUserTokenService iUserTokenService;

	@Autowired
	private IUserBasicService iUserBasicService;

	@Autowired
	private IUserSMSService iUserSMSService;

	/**
	 * 刷新令牌
	 *
	 * @param refreshTokenReqVO
	 * @param bindingResult
	 * @return
	 */
	@MethodValidate
	@NotNeedAccess
	@PostMapping(value = "refreshToken", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "刷新令牌(肖博)", httpMethod = "POST", notes = "刷新令牌(肖博)")
	public ResponseVO<RefreshTokenRespVO> refreshToken(@RequestBody @Valid RefreshTokenReqVO refreshTokenReqVO, HttpServletRequest request, BindingResult bindingResult) {
		logger.info(">>> 开始刷新令牌,请求参数：{} <<<", JSONObject.toJSONString(refreshTokenReqVO));
		RefreshTokenReqDTO refreshTokenReqDTO = ConvertUtils.convert(refreshTokenReqVO, RefreshTokenReqDTO.class);
		RefreshTokenRespDTO refreshTokenRespDTO = iUserBasicService.refreshToken(refreshTokenReqDTO, request);
		RefreshTokenRespVO refreshTokenRespVO = ConvertUtils.convert(refreshTokenRespDTO, RefreshTokenRespVO.class);
		logger.info(">>> 刷新令牌,响应报文：{} <<<", (null != refreshTokenRespVO ? JSONObject.toJSONString(refreshTokenRespVO):""));
		return ResponseVO.with(refreshTokenRespVO);
	}

	/**
	 * 获取api访问令牌
	 *
	 * @param requestVO
	 * @param bindingResult
	 * @return
	 */
	@MethodValidate
	@NotNeedAccess
	@PostMapping(value = "loginToken", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "登录并获取api访问令牌(肖博)", httpMethod = "POST", notes = "登录并获取api访问令牌(肖博)")
	public ResponseVO<LoginRespVO> loginForToken(@RequestBody @Valid LoginReqVO requestVO, HttpServletRequest request, BindingResult bindingResult) {
		logger.info(">>> 开始获取登录token ,请求参数：{} <<<", JSONObject.toJSONString(requestVO));
		ResponseVO<LoginRespVO> responseVO = new ResponseVO<LoginRespVO>();

		LoginReqDTO loginReqDTO = ConvertUtils.convert(requestVO,LoginReqDTO.class);
		LoginRespDTO loginRespDTO = iUserBasicService.loginForToken(loginReqDTO ,request);
		LoginRespVO loginRespVO = ConvertUtils.convert(loginRespDTO, LoginRespVO.class);
		logger.info(">>> 开始获取登录token ,响应报文：{} <<<", (null != loginRespVO ? JSONObject.toJSONString(requestVO):""));
		responseVO.setData(loginRespVO);
		responseVO.setCode(ResponseStatusEnum.OK.getCode());
		responseVO.setMessage(ResponseStatusEnum.OK.getMessage());
		return responseVO;
	}

	/**
	 * 发送(短信/邮箱)验证码
	 *
	 * @param userVerifiyCodeReqVO
	 * @param bindingResult
	 * @return
	 */
	@MethodValidate
	@NotNeedAccess
	@PostMapping(value = "/sendVerifiyCode", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "发送(短信/邮箱)验证码(肖博)", httpMethod = "POST", notes = "发送短信验证码(肖博)")
	public ResponseVO sendVerifiyCode(@RequestBody @Valid UserVerifiyCodeReqVO userVerifiyCodeReqVO, BindingResult bindingResult) {
		logger.info(">>>> 当前sendVerifiyCode请求参数：{} <<<",(null != userVerifiyCodeReqVO ? JSONObject.toJSONString(userVerifiyCodeReqVO) : ""));
		Integer accountType = userVerifiyCodeReqVO.getAccountType();
		if(accountType == LoginAccountTypeEnum.MOBILE.getCode()){
			Pattern pattern = Pattern.compile("(^1[34578]\\d{9}$)|(^1(66|73|77|88|98|99)\\d{8}$)");
			boolean matches = pattern.matcher(userVerifiyCodeReqVO.getAccountNumber()).matches();
			if(!matches){
				log.error(">>> 手机号格式不正确 <<<");
				throw new BaseBizException(ResponseStatusEnum.MOBILE_FORMAT_PARAMETER_ERROR);
			}
		}else if(accountType == LoginAccountTypeEnum.EMAIL.getCode()){
			Pattern pattern = Pattern.compile("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\\.[a-zA-Z0-9]{2,6}$");
			boolean matches = pattern.matcher(userVerifiyCodeReqVO.getAccountNumber()).matches();
			if(!matches){
				log.error(">>> email格式不正确 <<<");
				throw new BaseBizException(ResponseStatusEnum.EMAIL_FORMAT_PARAMETER_ERROR);
			}
		}
		//1.注册 2.登陆 3.账号安全(只有类型为2.登陆 3.账号安全才需要判断账号是否存在)
		Integer businessType = userVerifiyCodeReqVO.getBusinessType();
		/*if(businessType == VerifiyCodeTypeEnum.LOGIN.getValue().intValue() || businessType == VerifiyCodeTypeEnum.ACCOUNT_SECURITY.getValue().intValue() ){
			UserBase userBase = iUserBasicService.queryUserByUserName(userVerifiyCodeReqVO.getAccountNumber());
			if (null == userBase){
				logger.error(">>> 平台未注册该用户：{}",userVerifiyCodeReqVO.getAccountNumber());
				throw new BaseBizException(ResponseStatusEnum.NOT_REGISTER_USER_FAIL);
			}
		}*/
		if(accountType == LoginAccountTypeEnum.MOBILE.getCode()){
			VerifiyCodeTypeEnum verifiyCodeTypeEnum = VerifiyCodeTypeEnum.of(businessType.byteValue());
			SMSCodeReqDTO sMSCodeReqDTO = new SMSCodeReqDTO();
			sMSCodeReqDTO.setVerifiyCodeTypeEnum(verifiyCodeTypeEnum);
			sMSCodeReqDTO.setLoginMobileNo(userVerifiyCodeReqVO.getAccountNumber());
			sMSCodeReqDTO.setUserName(userVerifiyCodeReqVO.getAccountNumber());
			VerifiyCodeRespDTO verifiyCodeRespDTO = iUserSMSService.sendSMSAndGetCode(sMSCodeReqDTO);
			return (null != verifiyCodeRespDTO && verifiyCodeRespDTO.getSendStatus() ?ResponseVO.success():ResponseVO.error());
		}else if(accountType == LoginAccountTypeEnum.EMAIL.getCode()){
			VerifiyCodeTypeEnum verifiyCodeTypeEnum = VerifiyCodeTypeEnum.of(businessType.byteValue());
			EmailCodeReqDTO emailCodeReqDTO = new EmailCodeReqDTO();
			emailCodeReqDTO.setEmail(userVerifiyCodeReqVO.getAccountNumber());
			emailCodeReqDTO.setVerifiyCodeTypeEnum(verifiyCodeTypeEnum);
			boolean result = iUserSMSService.sendEmailAndGetCode(emailCodeReqDTO);
			return result ? ResponseVO.success(): ResponseVO.error();
		}else{
			log.error(">>> 传递的账户类型未知 <<<");
			return ResponseVO.error();
		}
	}


	/**
	 * 验证(短信/邮箱)验证码
	 *
	 * @param checkVerifyCodeReqVO
	 * @param bindingResult
	 * @return
	 */
	@MethodValidate
	@NotNeedAccess
	@PostMapping(value = "/checkVerifiyCode", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "验证(短信/邮箱)验证码(肖博)", httpMethod = "POST", notes = "验证(短信/邮箱)验证码(肖博)")
	public ResponseVO checkVerifiyCode(@RequestBody @Valid CheckVerifyCodeReqVO checkVerifyCodeReqVO,BindingResult bindingResult) {
		logger.info(">>>> 当前checkVerifiyCode请求参数：{} <<<",(null != checkVerifyCodeReqVO ? JSONObject.toJSONString(checkVerifyCodeReqVO) : ""));
		CheckVerifyCodeReqDTO checkVerifyCodeReqDTO = ConvertUtils.convert(checkVerifyCodeReqVO, CheckVerifyCodeReqDTO.class);
		boolean rs = iUserSMSService.checkVerifyCode(checkVerifyCodeReqDTO);
		return rs ? ResponseVO.success() : ResponseVO.with(ResponseVO.FAIL,"验证码错误","");
	}

	/**
	 * 注销登录
	 *
	 * @return
	 */
	@PostMapping(value = "logout", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "注销登录(肖博)", httpMethod = "POST", notes = "注销登录(肖博)")
	public EmptyResponseVO logout() {
		log.info(">>>> 当前logout请求开始 <<<");
		String userId = getCurrentUserId();
		log.info(">>>> 当前logout请求,userId:{} <<<", userId);

		String token = cacheContext.getAccessTokenForUserId(userId);
		iUserTokenService.expireToken(token);

		log.info(">>>> 当前logout请求完成 <<<");
		return EmptyResponseVO.getInstance();
	}

	/**
	 * 查询用户注册平台账号所获积分
	 *
	 * @param checkUserAccountReqVO
	 * @param bindingResult
	 * @return
	 */
	@ApiIgnore
	@MethodValidate
	@PostMapping(value = "/checkUserAccount", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ApiOperation(value = "检查用户账户(肖博)", httpMethod = "POST", notes = "检查用户账户(肖博)")
	public ResponseVO<CheckUserAccountRespVO> checkUserAccount(@RequestBody @Valid CheckUserAccountReqVO checkUserAccountReqVO, BindingResult bindingResult) {
		logger.info(">>>> 当前checkUserAccount请求参数：{} <<<", (null != checkUserAccountReqVO ? JSONObject.toJSONString(checkUserAccountReqVO) : ""));
		CheckUserAccountReqDTO checkUserAccountReqDTO = ConvertUtils.convert(checkUserAccountReqVO, CheckUserAccountReqDTO.class);
		CheckUserAccountRespDTO checkUserAccountRespDTO = iUserBasicService.checkUserAccount(checkUserAccountReqDTO);
		CheckUserAccountRespVO checkUserAccountRespVO = ConvertUtils.convert(checkUserAccountRespDTO, CheckUserAccountRespVO.class);
		logger.info(">>>> 当前checkUserAccount响应内容：{} <<<", (null != checkUserAccountRespVO ? JSONObject.toJSONString(checkUserAccountRespVO) : ""));
		return ResponseVO.with(checkUserAccountRespVO);
	}

}
